标签选选择器是 K8s 中的一个重要的组成部分,用于不同的 Pod 控制器控制此类标签的 Pod,用于 Service 进行后端的关联等,所以对 Pod 标签的操作显得尤为的种要。同时在基本的 Pod 配置清单中, Containers 部分的配置包含了镜像的拉取规则,当 Docker 和 配置清单都配置有要执行的命令时,到底执行那一部分的命令?Pod 有生命周期,当然我们也可以在容器启动和销毁之前做一些操作。包括容器的重启策略等。从这些知识点中可以看,K8s 在保证已经存活,并且达到用户理想的状态其实做了很多的工作,在了解之后的原理之后就会觉得很有意思。
镜像拉取规则 Pod.spec.containers 字段中,spec.containers 类型为<[] object>,格式如下。
1 2 3 - name <String> image <String> imagePullPolicy <String>, 支持的值有 Always(总是拉取, 默认值),Never(从不拉取),IfNotPresent(如果存在则不拉取)。默认是 Always,但是如果镜像是 latest 版本,那么也是总是拉取的,除非手动指定 imagePullPolicy
命令优先级 在 Docker 中,命令的执行有 cmd 和 entrypoint。如果只有 cmd 那么就执行 cmd 的内容,如果同时存在 entrypoint 和 cmd,那么会将 cmd 的值作为参数传入 entrypoint 中执行。
而在 K8s 中,没有了 cmd 和 entrypoint,而是有 command 和 args。command 相当于 docker 中的 entrypoint,args 相当于 docker 中的 cmd。
那么什么时候使用容器的命令,什么时候使用 k8s 资源清单中的命令就显得及其的重要了,具体可以分为以下四种情况:
如果没有提供 command 和 args,那么就默认使用 docker 镜像中的 cmd 和 entrypoint。
如果提供了 command 但是没有 args,那么就只运行 command,镜像中的 entrypoint 和 cmd 都被忽略。
如果提供了 args 但是没有 command,那么就使用镜像中的 entrypoint,args 将作为 entrypoint 的参数,镜像中的 cmd 将被忽略。
如果 command 和 args 都提供了,那么镜像中的 entrypoint 和 args 都将被忽略。
更多信息,可见 https://k8smeetup.github.io/docs/tasks/inject-data-application/define-command-argument-container/
标签操作 一个资源应用可能有多个标签,而一个标签也可以分布在不同的资源上。标签的灵活使用可以将资源从不同角度进行分组,从而实现不同的管理。标签的名称和值的长度为最大36个字符。
查看 Pod 显示标签 1 kubectl get pods --show-labels
1 2 NAME READY STATUS RESTARTS AGE LABELS nginx-deploy-5 c9b546997-nv2xp 1 /1 Running 0 4 h7m pod-template-hash=5 c9b546997,run=nginx-deploy
Pod 标签过滤 查看包含 app 的标签。显示结果新增一列,新增的一列为过滤的标签名称,下面显示过滤匹配的结果。-L 后面可跟多个标签,多个过滤的时候使用 “,” 进行分割。
1 2 3 4 [root@iZrj94q5l72imm6kxm11qvZ rexyan] NAME READY STATUS RESTARTS AGE APP nginx-deploy-5 c9b546997-nv2xp 1 /1 Running 0 4 h10m pod-demo 2 /2 Running 0 15 s myapp
表示只显示包含的 app 的标签,其余的不显示。后面也可跟多个标签,多个过滤的时候使用 “,” 进行分割。
1 2 NAME READY STATUS RESTARTS AGE pod-demo 2 /2 Running 0 4 m57s
Pod 新增标签 为 pod-demo 新增一个 release=canary 的标签。命令格式为 kubectl label + 资源类型 + 资源名称 + 标签值
1 kubectl label pods pod-demo release=canary
1 2 3 4 [root@iZrj94q5l72imm6kxm11qvZ rexyan] NAME READY STATUS RESTARTS AGE LABELS nginx-deploy-5 c9b546997-nv2 xp 1 /1 Running 0 4 h21m pod-template-hash=5 c9b546997,run=nginx-deploy pod-demo 2 /2 Running 0 10 m app=myapp,author=rexyan,release=canary
Pod修改标签 将上面的 release=canary 改为 release=stable,需要在刚才新增的命令上加上 –overwrite 选项。
1 kubectl label pods pod-demo release=stable --overwrite
1 2 3 4 [root@iZrj94q5l72imm6kxm11qvZ rexyan] NAME READY STATUS RESTARTS AGE LABELS nginx-deploy-5 c9b546997-nv2xp 1 /1 Running 0 4 h23m pod-template-hash=5 c9b546997,run=nginx-deploy pod-demo 2 /2 Running 0 13 m app=myapp,author=rexyan,release=stable
Node 查看标签 1 kubectl get node --show-labels
1 2 3 izrj94q5l72imm6kxm11qvz Ready master 4 h57m v1.14 .2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=izrj94q5l72imm6kxm11qvz,kubernetes.io/os=linux,node-role.kubernetes.io/master= izrj94q5l72imm6kxm11qwz Ready <none> 4 h50m v1.14 .2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=izrj94q5l72imm6kxm11qwz,kubernetes.io/os=linux izrj94q5l72imm6kxm11qxz Ready <none> 4 h51m v1.14 .2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=izrj94q5l72imm6kxm11qxz,kubernetes.io/os=linux
Node 新增标签 1 kubectl label nodes izrj94q5l72imm6kxm11qxz type=test
1 2 3 4 5 kubectl get node --show-labels NAME STATUS ROLES AGE VERSION LABELS izrj94q5l72imm6kxm11qvz Ready master 5 h10m v1.14 .2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=izrj94q5l72imm6kxm11qvz,kubernetes.io/os=linux,node-role.kubernetes.io/master=,type=master izrj94q5l72imm6kxm11qwz Ready <none> 5 h3m v1.14 .2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=izrj94q5l72imm6kxm11qwz,kubernetes.io/os=linux izrj94q5l72imm6kxm11qxz Ready <none> 5 h4m v1.14 .2 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=izrj94q5l72imm6kxm11qxz,kubernetes.io/os=linux,type=test
指定 Pod 调度节点 nodelSelecter Node 有标签,那我们就可以将一个 Pod 指定调度在哪一个节点上运行。在 Pod.spec 下有 nodelSelecter 字段,nodelSelecter 代表的意思是节点标签选择器。我们为之前的 pod-demo 设置 ports 和 nodeSelector,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 apiVersion: v1 kind: Pod metadata: name: pod-demo namespace: default labels: app: myapp author: rexyan spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http - containerPort: 80 - name: busybox image: busybox command: - "/bin/sh" - "-c" - "sleep 3600" nodeSelector: type: test
示例会将 pod 调度到 type=test 的 节点上。
1 2 kubectl delete -f pod-demo.yaml kubectl create -f pod-demo.yaml
1 2 3 4 kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-deploy-5 c9b546997-nv2xp 1 /1 Running 0 5 h7m 10.244 .1 .2 izrj94q5l72imm6kxm11qxz <none> <none> pod-demo 2 /2 Running 0 19 s 10.244 .1 .3 izrj94q5l72imm6kxm11qxz <none> <none>
可以看到两个容器均调度到了 izrj945l72imm6kxm11qxz 的节点上,而这个节点就是被打上 type=test 标签的节点。
查看 pod 的详细信息中的 default-scheduler 字段也可以看到调度的结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 kubectl describe pods pod-demo ...... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 3 m35s default-scheduler Successfully assigned default/pod-demo to izrj94q5l72imm6kxm11qxz Normal Pulling 3 m35s kubelet, izrj94q5l72imm6kxm11qxz Pulling image "ikubernetes/myapp:v1" Normal Pulled 3 m32s kubelet, izrj94q5l72imm6kxm11qxz Successfully pulled image "ikubernetes/myapp:v1" Normal Created 3 m32s kubelet, izrj94q5l72imm6kxm11qxz Created container myapp Normal Started 3 m32s kubelet, izrj94q5l72imm6kxm11qxz Started container myapp Normal Pulling 3 m32s kubelet, izrj94q5l72imm6kxm11qxz Pulling image "busybox" Normal Pulled 3 m30s kubelet, izrj94q5l72imm6kxm11qxz Successfully pulled image "busybox" Normal Created 3 m30s kubelet, izrj94q5l72imm6kxm11qxz Created container busybox Normal Started 3 m30s kubelet, izrj94q5l72imm6kxm11qxz Started container busybox
nodeName 使用 nodeName,可以直接将一个 Pod 指定运行在某个 node 上,根据 node 名称。
许多资源支持内嵌的字段来定义其自己使用的标签选择器:
matchLabels:表示直接给定键值就能进行选择
matchExpressions:表示要基于给定的表达式来进行选择
标签选择器 等值关系 可以使用 = ,== 或者 !=1 kubectl get pods -l author=rexyan
1 kubectl get pods -l author==rexyan,app=test
1 kubectl get pods -l author!=rexyan
集合关系 可以使用 KEY in (VALUE1, VALUE2) 或者 notin 或者 !KEY1 kubectl get pods -l "author in (rexyan, yanrunsha, runsha.yan)"
1 kubectl get pods -l "author notin (rexyan, yanrunsha, runsha.yan)"
Pod 注解 annotations 是 Pod 的注解。与 lable 不同的地方在于,他不能用于挑选资源对象,仅用于为对象提供 “元数据”
修改 pod-demo.yaml, 内容如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 apiVersion: v1 kind: Pod metadata: name: pod-demo namespace: default labels: app: myapp author: rexyan annotations: rexyan.me/create-by: "rexyan" spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 - name: busybox image: busybox command: - "/bin/sh" - "-c" - "sleep 3600" nodeSelector: type: test
将 pod 删除,并且重新创建
1 2 kubectl delete -f pod-demo.yaml kubectl create -f pod-demo.yaml
可以使用 describe 查看资源的注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 kubectl describe pods pod-demo Name: pod-demo Namespace: default Priority: 0 PriorityClassName: <none> Node: izrj94q5l72imm6kxm11qxz/172.20 .245 .188 Start Time: Sat, 18 May 2019 22 :27 :11 +0800 Labels: app=myapp author=rexyan Annotations: rexyan.me/create-by: rexyan Status: Running IP: 10.244 .1 .4 Containers: myapp: Container ID: docker://0 f3a448bb2c66d26c060ebf0fb65941265dc8b2cf9cb837fed88641e5478df0f Image: ikubernetes/myapp:v1 Image ID: docker-pullable://docker.io/ikubernetes/myapp@sha256:9 c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513 Port: 80 /TCP Host Port: 0 /TCP State: Running Started: Sat, 18 May 2019 22 :27 :12 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-8 dmfd (ro) busybox: Container ID: docker://89e2 a12051d98435c427f091b4753a2900455641b397a5396f59b16426561c06 Image: busybox Image ID: docker-pullable://docker.io/busybox@sha256:4 b6ad3a68d34da29bf7c8ccb5d355ba8b4babcad1f99798204e7abb43e54ee3d Port: <none> Host Port: <none> Command: /bin/sh -c sleep 3600 State: Running Started: Sat, 18 May 2019 22 :27 :13 +0800 Ready: True Restart Count: 0 Environment: <none> Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-8 dmfd (ro) Conditions: Type Status Initialized True Ready True ContainersReady True PodScheduled True Volumes: default-token-8 dmfd: Type: Secret (a volume populated by a Secret) SecretName: default-token-8 dmfd Optional: false QoS Class: BestEffort Node-Selectors: type=test Tolerations: node.kubernetes.io/not -ready:NoExecute for 300 s node.kubernetes.io/unreachable:NoExecute for 300 s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 18 s default-scheduler Successfully assigned default/pod-demo to izrj94q5l72imm6kxm11qxz Normal Pulled 17 s kubelet, izrj94q5l72imm6kxm11qxz Container image "ikubernetes/myapp:v1" already present on machine Normal Created 17 s kubelet, izrj94q5l72imm6kxm11qxz Created container myapp Normal Started 17 s kubelet, izrj94q5l72imm6kxm11qxz Started container myapp Normal Pulling 17 s kubelet, izrj94q5l72imm6kxm11qxz Pulling image "busybox" Normal Pulled 16 s kubelet, izrj94q5l72imm6kxm11qxz Successfully pulled image "busybox" Normal Created 16 s kubelet, izrj94q5l72imm6kxm11qxz Created container busybox Normal Started 16 s kubelet, izrj94q5l72imm6kxm11qxz Started container busybox
Pod 的生命周期 状态:Pending,Running,Failed,Succeeded,Unknow……
Pod 生命周期中的重要行为:
1 2 3 4 初始化容器 容器探测: liveness(用来判定容器是否正常) readiness(用来判定容器中的服务是否正常)
容器重启策略 restartPolicy 用于定义容器的充气策略。支持以下几种。
Always(默认),OnFailure(失败后才重启),Never(从不重启)
进入容器和日志查看 查看容器日志和进入容器分别使用kubectl logs
和 kubectl exec
命令。当 Pod 中只有一个容器的时候,我们可以不使用 -c
参数指定进入哪一个容器,但是如果 Pod 中有多个容器的时候,就需要使用-c
来指定具体的容器。